package com.zhang.study.chapter03;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Stack;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.zhang.util.RandomArrayUtil.generateRandomArray;

/**
 * 使用单链表实现栈结构
 */
public class Code04_NodeMyStack {

    public static class Node<T> {
        public T value;

        public Node<T> next;

        public Node() {
        }

        public Node(T value) {
            this.value = value;
        }
    }

    public static class NodeMyStack<T> {
        public Node<T> head;

        public NodeMyStack() {
        }

        public NodeMyStack(Collection<T> collection) {
            if (collection == null || collection.isEmpty()) {
                throw new RuntimeException("collection is empty");
            }
            for (T t : collection) {
                push(t);
            }
        }


        /**
         * 实现元素入栈出栈功能
         */

        public void push(T data) {
            Node<T> tNode = new Node<>(data);
            if (head != null) {
                tNode.next = head;
            }
            head = tNode;
        }


        public T pop() {
            if (head == null) {
                return null;
            }
            Node<T> cur = head;

            head = head.next;

            return cur.value;
        }


    }


    public static void main(String[] args) {
        int len = 5000;
        int value = 10000;
        int testTime = 10000;
        int sizeTime;
        System.out.println("test begin!");
        for (int i = 0; i < testTime; i++) {
            // 生成链表头结点
            int[] intArr = generateRandomArray(len, value);
            List<Integer> collect = IntStream.of(intArr).boxed().collect(Collectors.toList());
            NodeMyStack<Integer> nodeMyStack = new NodeMyStack<>(collect);
            Stack<Integer> stack = new Stack<>();
            for (Integer integer : collect) {
                stack.push(integer);
            }
            sizeTime = collect.size() - 1;
            if (!testMyStack(nodeMyStack, stack, sizeTime)) {
                System.out.println("Oops!");

                System.out.println(nodeMyStack);
            }
        }
        System.out.println("test finish!");
    }

    private static boolean testMyStack(NodeMyStack<Integer> nodeMyStack, Stack<Integer> stack, int sizeTime) {
        int times = sizeTime;
        while (times >= 0) {
            double random = Math.random();
            int i = (int) (Math.random() * 100 - Math.random() * 10);
            if (random >= 0.5) {
                // 入栈
                nodeMyStack.push(i);
                stack.push(i);
            } else {
                // 出栈
                Integer pop1 = nodeMyStack.pop();
                Integer pop2 = stack.pop();
                if (!Objects.equals(pop1, pop2)) {
                    return false;
                }
            }
            times--;
        }
        while (!stack.isEmpty()) {
            Integer pop1 = stack.pop();
            Integer pop2 = nodeMyStack.pop();
            if (!Objects.equals(pop1, pop2)) {
                return false;
            }
        }
        return true;
    }

}
